package com.xnx.bincker.leader.core.domain;

import com.xnx.bincker.leader.utils.StringUtils;
import lombok.Data;
import lombok.extern.log4j.Log4j2;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import java.io.Serializable;
import java.lang.annotation.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;

@Data
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
@Log4j2
public class BasicEntity implements Serializable {
    private static final long serialVersionUID = 3658464590221451729L;

    /**
     * 创建时间
     */
    @CreatedDate
	private Date createdDate;

    /**
     * 最后修改时间
     */
	@LastModifiedDate
	private Date lastModifiedDate;

    /**
     * 插入字段注解
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
	public @interface Insert{}

    /**
     * 更新字段注解
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
	public @interface Update{}

    /**
     * 搜索字段注解
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
	public @interface Search{}

    /**
     * 拷贝另一个对象中含有某个注解的属性到本对象
     * @param annotation 注解类
     * @param pojo 对象
     */
	public void copyProperties(Class<? extends Annotation> annotation, BasicEntity pojo) {
	    Class<? extends BasicEntity> cls = getClass();
        for (Field field : cls.getDeclaredFields()) {
            if(!field.isAnnotationPresent(annotation)) continue;
            try {
                String fieldName = StringUtils.firstCharUpperCase(field.getName());
                Method reader = cls.getDeclaredMethod("get" + fieldName);
                Method writer = cls.getDeclaredMethod("set" + fieldName, field.getType());
                writer.invoke(this, reader.invoke(pojo));
            } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                log.error(e);
            }
        }
    }

    /**
     * 拷贝自身的部分属性到新的对象
     */
    public BasicEntity cloneByAnnotation(Class<? extends Annotation> annotation){
	    Class<? extends BasicEntity> cls = getClass();
        try {
            BasicEntity instance = cls.newInstance();
            instance.copyProperties(annotation, this);
            return instance;
        } catch (InstantiationException | IllegalAccessException e) {
            log.error(e);
        }
        return null;
    }

    /**
     * 数据验证分组
     */
    public interface ValidGroup{
        /**
         * 插入
         */
        interface Insert extends ValidGroup{}

        /**
         * 搜索
         */
        interface Search extends ValidGroup{}

        /**
         * 更新
         */
        interface Update extends ValidGroup{}
    }
}
